package com.talkweb.platform.commonapi.query;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.talkweb.platform.commonapi.query.QueryCondition.Operator;
import com.talkweb.platform.commonapi.query.QueryCondition.Prepender;

import io.swagger.annotations.ApiModelProperty;

/**
 * 
 * 查询条件树
 * 
 * @author lzy
 */
public class QueryTree implements Serializable {

	/**
	 * <属性变量说明>
	 * 
	 */
	private static final long serialVersionUID = -7992805146439723080L;

	/**
	 * 分页参数
	 */
	@ApiModelProperty(value = "分页参数")
	private Pagination pagination = new Pagination();

	/**
	 * 查询条件(支持嵌套)
	 */
	@ApiModelProperty(value = "查询条件(支持嵌套)")
	private List<QueryCondition> conditions = new ArrayList<QueryCondition>();

	/**
	 * 排序参数
	 */
	@ApiModelProperty(value = "排序参数")
	private List<OrderMethod> orderMethods;

	/**
	 * 单表查询
	 */
	@ApiModelProperty(value = "是否单表查询(默认为true)")
	private boolean singleTable = true;

	private Class<? extends Serializable> clazz;

	public Pagination page(int pageNo, int numPerPage, boolean calTotal) {
		if (null == pagination) {
			pagination = new Pagination();
		}
		pagination.setPageNo(pageNo);
		pagination.setPageSize(numPerPage);
		pagination.setCalTotal(calTotal);
		return pagination;
	}

	public Pagination page(int pageNo, int numPerPage) {
		return page(pageNo, numPerPage, true);
	}

	public List<QueryCondition> addCondition(QueryCondition condition) {
		this.conditions.add(condition);
		return this.conditions;
	}

	public QueryCondition getQueryCondition(String fieldName) {
		if (null == this.conditions || null == fieldName) {
			return null;
		}
		for (QueryCondition condition : this.conditions) {
			if (fieldName.equals(condition.getFieldName())) {
				return condition;
			}
		}
		return null;
	}

	/**
	 * 设置第一个条件
	 *
	 * @param fieldName
	 * @param operator
	 * @param fieldValues
	 * @return QueryTree [返回类型说明]
	 * @see [类、类#方法、类#成员]
	 */
	public QueryTree where(String fieldName, Operator operator, Object... fieldValues) {
		return condition(new QueryCondition(fieldName, null, operator, fieldValues));
	}

	/**
	 * 设置第一个条件
	 *
	 * @param condition
	 * @return QueryTree [返回类型说明]
	 * @see [类、类#方法、类#成员]
	 */
	public QueryTree where(QueryCondition condition) {
		condition.setPrepender(null);
		return condition(condition);
	}

	/**
	 * 添加AND条件
	 *
	 * @param fieldName
	 * @param operator
	 * @param fieldValues
	 * @return QueryTree [返回类型说明]
	 * @see [类、类#方法、类#成员]
	 */
	public QueryTree and(String fieldName, Operator operator, Object... fieldValues) {
		return condition(new QueryCondition(fieldName, Prepender.AND, operator, fieldValues));
	}

	/**
	 * 使用in 构造条件
	 * 
	 * @param fieldName
	 * @param fieldValues
	 * @return [参数说明]
	 * 
	 * @return QueryTree [返回类型说明]
	 * @exception throws
	 *                [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public QueryTree and_in(String fieldName, Collection<?> fieldValues) {
		return condition(new QueryCondition(fieldName, Prepender.AND, Operator.IN, fieldValues));
	}

	/**
	 * 使用in 构造条件 <功能详细描述>
	 * 
	 * @param fieldName
	 * @param fieldValues
	 * @return [参数说明]
	 * 
	 * @return QueryTree [返回类型说明]
	 * @exception throws
	 *                [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public QueryTree and_in(String fieldName, Object[] fieldValues) {
		return condition(new QueryCondition(fieldName, Prepender.AND, Operator.IN, fieldValues));
	}

	/**
	 * 使用not in 构造条件
	 * 
	 * @param fieldName
	 * @param fieldValues
	 * @return [参数说明]
	 * 
	 * @return QueryTree [返回类型说明]
	 * @exception throws
	 *                [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public QueryTree and_notIn(String fieldName, Collection<?> fieldValues) {
		return condition(new QueryCondition(fieldName, Prepender.AND, Operator.NOT_IN, fieldValues));
	}

	/**
	 * 使用 not in 构造条件 <功能详细描述>
	 * 
	 * @param fieldName
	 * @param fieldValues
	 * @return [参数说明]
	 * 
	 * @return QueryTree [返回类型说明]
	 * @exception throws
	 *                [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	public QueryTree and_notIn(String fieldName, Object[] fieldValues) {
		return condition(new QueryCondition(fieldName, Prepender.AND, Operator.NOT_IN, fieldValues));
	}

	/**
	 * 添加AND条件
	 *
	 * @param condition
	 * @return QueryTree [返回类型说明]
	 * @see [类、类#方法、类#成员]
	 */
	public QueryTree and(QueryCondition condition) {
		condition.setPrepender(Prepender.AND);
		return condition(condition);
	}

	/**
	 * 添加OR条件
	 *
	 * @param fieldName
	 * @param operator
	 * @param fieldValues
	 * @return QueryTree [返回类型说明]
	 * @see [类、类#方法、类#成员]
	 */
	public QueryTree or(String fieldName, Operator operator, Object... fieldValues) {
		return condition(new QueryCondition(fieldName, Prepender.OR, operator, fieldValues));
	}

	/**
	 * 添加OR条件
	 *
	 * @param condition
	 * @return QueryTree [返回类型说明]
	 * @see [类、类#方法、类#成员]
	 */
	public QueryTree or(QueryCondition condition) {
		condition.setPrepender(Prepender.OR);
		return condition(condition);
	}

	private QueryTree condition(QueryCondition condition) {
		if (null == condition.getPrepender() || null == this.conditions) {
			this.conditions = new ArrayList<QueryCondition>();
		}
		this.conditions.add(condition);
		return this;
	}

	public Pagination getPagination() {
		return pagination;
	}

	public void setPagination(Pagination pagination) {
		this.pagination = pagination;
	}

	public List<QueryCondition> getConditions() {
		return conditions;
	}

	public void setConditions(List<QueryCondition> conditions) {
		this.conditions = conditions;
	}

	public List<OrderMethod> getOrderMethods() {
		return orderMethods;
	}

	public void setOrderMethods(List<OrderMethod> orderMethods) {
		this.orderMethods = orderMethods;
	}

	public boolean isSingleTable() {
		return singleTable;
	}

	public void setSingleTable(boolean singleTable) {
		this.singleTable = singleTable;
	}

	public Class<? extends Serializable> getClazz() {
		return clazz;
	}

	public QueryTree setClazz(Class<? extends Serializable> clazz) {
		this.clazz = clazz;
		return this;
	}

}
